package cn.mw.cmdb.entity;

import cn.mw.cmdb.enums.NumericalTypeEnum;
import cn.mw.cmdb.enums.RoundIngModeEnum;
import cn.mw.cmdb.param.ImportContextParam;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.components.mongodb.entity.MPropertyTypeNumerical;
import cn.mw.microMonitorCommon.entity.cmdb.ModelExportDataInfoParam;
import cn.mw.microMonitorCommon.entity.cmdb.MwImportResultParam;
import com.google.common.base.Strings;
import org.springframework.data.mongodb.core.query.Criteria;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.mw.cmdb.enums.IntegerTypeEnum.DecimalType;
import static cn.mw.cmdb.enums.IntegerTypeEnum.IntegerType;
import static cn.mw.cmdb.util.ValConvertUtil.intValueConvert;

public class PropertyTypeNumerical extends PropertyType<PropertyTypeNumerical, BigDecimal> {
    public static final String ID = MPropertyTypeNumerical.ID;

    private MPropertyTypeNumerical mPropertyTypeNumerical = new MPropertyTypeNumerical();

    public PropertyTypeNumerical() {
        setId(ID);
        setName("数值型");
        setValueTip("请输入数字");
    }

    @Override
    public boolean validateValue(Object value, PropertyTypeRef propertyTypeRef) throws Exception {
        if (value instanceof String && !Strings.isNullOrEmpty(strValueConvert(value)) ) {
            BigDecimal bigDecimal = new BigDecimal(value.toString());
        }
        return true;
    }

    public Object convertValue(Object value) {
//        if (null != value && !Strings.isNullOrEmpty(strValueConvert(value))) {
//            return new BigDecimal(strValueConvert(value));
//        }
        if (null != value ) {
            return value;
        }
        return new BigDecimal(0);
    }


    @Override
    public Object getDataValue(ImportContextParam contextParam) {
        MwImportResultParam resultParam = new MwImportResultParam();
        String message = "";
        ModelExportDataInfoParam importParam = contextParam.getParam();
        //属性名称
        String tableName = importParam.getTableName();
        Object cellValue = importParam.getCellValue();
        Map<String, Object> matchMap = new HashMap<>();
        importCheckInfo(resultParam, contextParam, matchMap);
        message += resultParam.getMessage();
        boolean isDefaultFlag = false;
        //数值类型为空字符串
        if(Strings.isNullOrEmpty(strValueConvert(cellValue).trim())){
            //空字符串
            if(matchMap!=null && matchMap.get(ValueKey)!=null){
                Object obj = matchMap.get(ValueKey);
                isDefaultFlag = true;
                cellValue = obj;
            }else{
                return resultParam;
            }
        }
        //是否默认值提示
        String prefixStr = prefixStrKey;
        if (isDefaultFlag) {
            prefixStr = defaultPrefixStrKey;
        }
        Object value = null;
        if (!Strings.isNullOrEmpty(strValueConvert(cellValue)) && !isNumeric(cellValue)) {
            message = tableName +prefixStr+ strValueConvert(cellValue) + "]必须是数字";
        } else {
            RoundingMode roundingMode = RoundingMode.HALF_UP;
            BigDecimal bigDecimal = new BigDecimal(strValueConvert(cellValue));
            value = bigDecimal;
            Integer scaleNum = 2;
            if (matchMap != null) {
                //最大值
                if (matchMap.get(maxNumKey) != null) {
                    BigDecimal bigDecimalMax = new BigDecimal(strValueConvert(matchMap.get(maxNumKey)));
                    //导入数据大于最大值
                    if (bigDecimal.compareTo(bigDecimalMax) > 0) {
                        message += tableName + prefixStr+ strValueConvert(cellValue) + "]不能大于最大值:[" + strValueConvert(matchMap.get(maxNumKey)) + "];";
                    }
                }
                //最小值
                if (matchMap.get(minNumKey) != null) {
                    BigDecimal bigDecimalMin = new BigDecimal(strValueConvert(matchMap.get(minNumKey)));
                    //导入数据大于最大值
                    if (bigDecimal.compareTo(bigDecimalMin) < 0) {
                        message += tableName + prefixStr + strValueConvert(cellValue) + "]不能小于最小值:[" + strValueConvert(matchMap.get(minNumKey)) + "];";
                    }
                }


                //数值正负类型(1:非负数；2:负数)
                Integer numericalType = intValueConvert(matchMap.get(numericalTypeKey));
                //非负数校验

                //正数或0匹配
                String reg = "^[0-9]+(\\.[0-9]+)?$";
                Pattern pattern = Pattern.compile(reg);
                Matcher matcher = pattern.matcher(strValueConvert(cellValue));
                boolean matchFlag = matcher.find();
                if (matchFlag && NumericalTypeEnum.negative.getCode().equals(numericalType)) {
                    message += tableName + prefixStr + strValueConvert(cellValue) + "]必须是负数;";
                }
                if (!matchFlag && NumericalTypeEnum.nonnegative.getCode().equals(numericalType)) {
                    message += tableName + prefixStr + strValueConvert(cellValue) + "]必须是正数或0;";
                }

                //整数匹配
                String reg2 = "^-?[0-9]+$";
                Pattern pattern2 = Pattern.compile(reg2);
                Matcher matcher2 = pattern2.matcher(strValueConvert(cellValue));
                //true为整数，false为小数
                boolean matchFlag2 = matcher2.find();

                //数值类型//1:整数；2:小数
                Integer integerTyp = intValueConvert(matchMap.get(integerTypeKey));
                //数据类型为小数，设置的校验类型为整数
                if (!matchFlag2 && IntegerType.getCode().equals(integerTyp)) {
                    message += tableName + prefixStr+ strValueConvert(cellValue) + "]必须是整数;";
                }
//                //数据类型为整数，设置的校验类型为小数
//                if (matchFlag2 && DecimalType.getCode().equals(integerTyp)) {
//                    message += tableName + prefixStr + strValueConvert(cellValue) + "]必须是小数;";
//                }
                //保留小数点位数（默认2位）
                scaleNum = matchMap.get(decimalLengthKey) ==null ? 2 :intValueConvert(matchMap.get(decimalLengthKey));
                int roundingModel = intValueConvert(matchMap.get(roundingModeKey));
                //小数类型且校验通过,进行小数格式处理
                if (DecimalType.getCode().equals(integerTyp)) {
                    if (roundingModel == RoundIngModeEnum.HALF_UP.getCode().intValue()) {
                        roundingMode = RoundingMode.HALF_UP;
                    }
                    if (roundingModel == RoundIngModeEnum.DOWN.getCode().intValue()) {
                        roundingMode = RoundingMode.DOWN;
                    }
                    if (roundingModel == RoundIngModeEnum.UP.getCode().intValue()) {
                        roundingMode = RoundingMode.UP;
                    }
                    value = bigDecimal.setScale(scaleNum, roundingMode);
                }
            }
            resultParam.setCellValue(value);
        }
        resultParam.setMessage(message);
        return resultParam;
    }

    @Override
    public Object lookValue(Object val, Map<String, Object> context) {
        return readValue(val,context);
    }
    @Override
    public Criteria doCriteria(CriteriaOpsType opsType, String name, Object value) {
        return mPropertyTypeNumerical.doCriteria(opsType, name, value);
    }

    @Override
    public CriteriaOpsType getDefaultCriteriaOpsType() {
        return CriteriaOpsType.is;
    }

    @Override
    public PropertyTypeNumerical newObj() {
        return new PropertyTypeNumerical();
    }

    public static boolean isNumeric(Object obj) {
        String str = strValueConvert(obj);
        // 正则表达式匹配数字格式
        String numericPattern = "^[-+]?\\d*\\.?\\d+$";
        return Pattern.matches(numericPattern, str);
    }

    @Override
    public void refresh() {

    }
}
